#ifndef SCON_OPERATION_TEST_H_
#define SCON_OPERATION_TEST_H_

#include "gtest/gtest.h"
#include "scon_operation.h"
#include "scon_file.h"


//namespace {

//template<class InputIter> ::testing::AssertionResult ArraysIsEqual(InputIter begin1, InputIter end1, InputIter begin2) {
	//InputIter it1 = begin1;
	//InputIter it2 = begin2;
	//while(it1 != end1) {
		//if (*it1 != *it2) {
			//return ::testing::AssertionFailure() << "Arrays is not equal";
		//}[> end of if <]

		//++it1;
		//++it2;
	//}//end of while

	//return ::testing::AssertionSuccess();
//}//end of template<class InputIter> ::testing::AssertionResult ArraysIsEqual()

//}


namespace SCon {

class OperationTest: public ::testing::Test {
public:
	std::string errorMessage;

	virtual void SetUp() {
		errorMessage = "";
	}//end of virtual void SetUp()

	virtual void TearDown() {}//end of virtual void TearDown()

};//end of declaration class OperationTest: public ::testing::Test

TEST_F(OperationTest, SyncAsycnIO_RequestHandlerTest){
//тестируем функцию SycnAsync<>::RequestHandler
	std::string path = "C:\\operationTest.txt";
	unsigned char* buf = new unsigned char[1024];
	unsigned char* buf1= new unsigned char[1024];
	long unsigned int size = 0;
	for (int i = 0; i < 1024; ++i) {
		buf[i] = i & 0xff;
	}//end of for

	File* f  = File::Create(path, File::RECREATE | File::READ | File::WRITE, &errorMessage);
	SyncAsyncIO<File> op;
	op.Initialize(f->fileDescriptor_);
	op.jobQueue_.push(typename SyncAsyncIO<File>::Job(buf, 1024, &size, SyncAsyncIO<File>::Job::WRITE, &errorMessage));
	SetEvent(op.request_);
	WaitForSingleObject(op.operationIsDone_, INFINITE);
	EXPECT_EQ(size, 1024);
	EXPECT_STREQ(errorMessage.c_str(), "");
	File::Close(f);
	
	f = File::Create(path, File::OPEN | File::READ | File::WRITE, &errorMessage);
	op.deviceDescriptor_ = f->fileDescriptor_;
	size = 0;
	op.jobQueue_.push(SyncAsyncIO<File>::Job(buf1, 1024, &size, SyncAsyncIO<File>::Job::READ, &errorMessage));
	SetEvent(op.request_);
	WaitForSingleObject(op.operationIsDone_, INFINITE);
	EXPECT_EQ(size, 1024);
	EXPECT_STREQ(errorMessage.c_str(), "");
	EXPECT_TRUE(ArraysIsEqual(buf, buf+1024, buf1));

	op.jobQueue_.push(SyncAsyncIO<File>::Job(0, 0, 0, SyncAsyncIO<File>::Job::FINISH, &errorMessage));
	SetEvent(op.request_);
	EXPECT_STREQ(errorMessage.c_str(), "");

	op.Destroy();
	File::Close(f);
}

TEST_F(OperationTest, SyncAsyncIO_AsyncReadTest){
//Тестируем функцию SyncAsync<>::AsyncRead()
	std::string path = "C:\\operationTest.txt";
	unsigned char* buf = new unsigned char[1024];
	unsigned char* buf1= new unsigned char[1024];
	long unsigned int size = 0;
	for (int i = 0; i < 1024; ++i) {
		buf[i] = i & 0xff;
	}//end of for

	File* f  = File::Create(path, File::RECREATE | File::READ | File::WRITE, &errorMessage);
	WriteFile(f->fileDescriptor_, buf, 1024, &size, 0);

	SyncAsyncIO<File> op;
	op.Initialize(f->fileDescriptor_);
	FutureResult res = op.AsyncRead(1024, buf1, &errorMessage);
	int actualDataSize = res.GetResult();
	EXPECT_EQ(actualDataSize, 1024);
	EXPECT_TRUE(ArraysIsEqual(buf, buf+1024, buf1));
	File::Close(f);

	for (int i = 0; i < 1024; ++i) {
		buf1[i] = 0;
	}//end of for
	f  = File::Create(path, File::OPEN | File::READ | File::WRITE, &errorMessage);
	res = op.AsyncRead(1024, 0, &errorMessage);
	actualDataSize = res.GetResult(buf1);
	EXPECT_EQ(actualDataSize, 1024);
	EXPECT_TRUE(ArraysIsEqual(buf, buf+1024, buf1));
	File::Close(f);
}

} /* SCon */ 

#endif /* end of include guard: SCON_OPERATION_TEST_H_ */

